package net.lab1024.sa.admin.module.business.erp.prp.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.erp.bas.dao.BomordDao;
import net.lab1024.sa.admin.module.business.erp.bas.dao.GoodsDao;
import net.lab1024.sa.admin.module.business.erp.bas.domain.entity.BomordEntity;
import net.lab1024.sa.admin.module.business.erp.bas.domain.entity.GoodsEntity;
import net.lab1024.sa.admin.module.business.erp.inv.dao.InventordDao;
import net.lab1024.sa.admin.module.business.erp.inv.domain.vo.TargetVo;
import net.lab1024.sa.admin.module.business.erp.prp.dao.*;
import net.lab1024.sa.admin.module.business.erp.prp.domain.entity.*;
import net.lab1024.sa.admin.module.business.erp.prp.domain.form.PrpordAddForm;
import net.lab1024.sa.admin.module.business.erp.prp.domain.form.PrpordQueryForm;
import net.lab1024.sa.admin.module.business.erp.prp.domain.form.PrpordUpdateForm;
import net.lab1024.sa.admin.module.business.erp.prp.domain.vo.PrpordVO;
import net.lab1024.sa.admin.module.business.erp.prp.domain.vo.PrpordaVO;
import net.lab1024.sa.admin.module.business.erp.sao.service.SaordService;
import net.lab1024.sa.base.common.code.ErpErrorCode;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import net.lab1024.sa.base.module.support.redis.RedisService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 生产计划 Service
 *
 * @Author AKITA
 * @Date 2025-08-08 15:03:13
 * @Copyright AKITA
 */

@Slf4j
@Service
public class PrpordService {

    @Resource
    private PrpordDao prpordDao;
    @Resource
    private PrpordaDao prpordaDao;
    @Resource
    private BomordDao bomordDao;
    @Resource
    private GoodsDao goodsDao;
    @Resource
    private BipordDao bipordDao;
    @Resource
    private BipordaDao bipordaDao;
    @Resource
    private BipordbDao bipordbDao;
    @Resource
    private SaordService saordService;
    @Resource
    private InventordDao inventordDao;
    @Resource
    private RedisService redisService;

    private final ReentrantLock reentrantLock = new ReentrantLock();
    /**
     * 分页查询
     */
    public PageResult<PrpordVO> queryPage(PrpordQueryForm queryForm) {
        Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
        List<PrpordVO> list = prpordDao.queryPage(page, queryForm);
        return SmartPageUtil.convert2PageResult(page, list);
    }


    public PageResult<PrpordVO> queryPageUnexecut(PrpordQueryForm queryForm) {
        Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
        List<PrpordVO> list = prpordDao.queryPageUnexecut(page, queryForm);
        return SmartPageUtil.convert2PageResult(page, list);
    }


    @Transactional
    public ResponseDTO<Long> add(PrpordAddForm addForm) {

        /*
         * 1、判断销售订单是否为最新数据
         * 2、同一版本号新增生产计划
         * 3、更新版本
         *
         *
         * */
        PrpordEntity prpordEntity = SmartBeanUtil.copy(addForm, PrpordEntity.class);

        prpordDao.insert(prpordEntity);
        List<PrpordaEntity> lista = addForm.getLista();
        for (PrpordaEntity prpordaEntity : lista) {
            prpordaEntity.setId(prpordEntity.getId());
            prpordaDao.insert(prpordaEntity);
        }

        if (!saordService.upDateVesrion(addForm.getBaseId(), addForm.getBaseVersion())) {
            throw new RuntimeException("数据异常，刷新重试!");
        }

        return ResponseDTO.ok(prpordEntity.getId());


    }





    /**
     * 更新
     */
    public ResponseDTO<String> update(PrpordUpdateForm updateForm) {
        PrpordEntity prpordEntity = SmartBeanUtil.copy(updateForm, PrpordEntity.class);
        prpordDao.updateById(prpordEntity);
        return ResponseDTO.ok();
    }

    /**
     * 批量删除
     */
    public ResponseDTO<String> batchDelete(List<Long> idList) {
        prpordDao.deleteBatchIds(idList);
        return ResponseDTO.ok();
    }



    @Transactional
    public ResponseDTO<String> delete(Long id) {

        List<BipordaEntity> bipordaEntities = bipordaDao.selectList(new LambdaQueryWrapper<BipordaEntity>().eq(BipordaEntity::getBaseId, id));

        if (!bipordaEntities.isEmpty()){
            return ResponseDTO.error(ErpErrorCode.PARAM_ERROR,"存在BIP运算单，禁止删除！");
        }

        prpordDao.deleteById(id);
        prpordaDao.deleteById(id);
        return ResponseDTO.ok();
    }




    public ResponseDTO<PrpordVO> info(Long id) {
        PrpordEntity prpordEntity = prpordDao.selectById(id);
        PrpordVO copy = SmartBeanUtil.copy(prpordEntity, PrpordVO.class);


        List<PrpordaEntity> prpordaEntities = prpordaDao.selectList(new LambdaQueryWrapper<PrpordaEntity>().eq(PrpordaEntity::getId, id));


        List<PrpordaVO> prpordaVOS = SmartBeanUtil.copyList(prpordaEntities, PrpordaVO.class);

        copy.setLista(prpordaVOS);

        ArrayList<TargetVo> targetVob = new ArrayList<>();
        for (PrpordaVO puordaVO : prpordaVOS) {
            if (puordaVO.getBaseId() != null) {
                TargetVo targetVo = new TargetVo();
                targetVo.setId(puordaVO.getBaseId());
                targetVo.setLineNum(puordaVO.getBaseLineNum());
                targetVo.setItemId(puordaVO.getItemId());
                targetVo.setItemName(puordaVO.getItemName());
                targetVo.setQty(puordaVO.getQty());
                targetVob.add(targetVo);
            }
        }


        copy.setListb(targetVob);


        List<BipordaEntity> bipordaEntities = bipordaDao.selectList(new LambdaQueryWrapper<BipordaEntity>().eq(BipordaEntity::getBaseId, id));


        ArrayList<TargetVo> targetVoc = new ArrayList<>();


        for (BipordaEntity item : bipordaEntities) {
            TargetVo targetVo = new TargetVo();
            targetVo.setId(item.getId());
            targetVo.setLineNum(item.getLineNum());
            targetVo.setItemId(item.getItemId());
            targetVo.setItemName(item.getItemName());
            targetVo.setQty(item.getQty());
            targetVoc.add(targetVo);
        }
        copy.setListc(targetVoc);

        return ResponseDTO.ok(copy);
    }


    public ResponseDTO<PrpordVO> infoUnexecute(Long id) {
        PrpordEntity prpordEntity = prpordDao.selectById(id);
        PrpordVO copy = SmartBeanUtil.copy(prpordEntity, PrpordVO.class);
        List<PrpordaVO> prpordaVOS = prpordaDao.infoUnexecute(id);
        copy.setLista(prpordaVOS);
        return ResponseDTO.ok(copy);
    }

    @Transactional
    public ResponseDTO<Long> breakDown(List<PrpordaVO> prpordaVOS) throws InterruptedException {

        BipordEntity bipordEntity = new BipordEntity();








        int count = 0;


        boolean booleanLock = reentrantLock.tryLock();

        if (booleanLock){


            try{


                count++;
                redisService.set("key",String.format("获取线程锁失败，用户{%s}正在使用线程{%s}分解生产计划,%s", SmartRequestUtil.getRequestUser().getUserName(), Thread.currentThread().getName(),count));

                bipordDao.insert(bipordEntity);
                int lineNum = 0;

                ArrayList<BipordbEntity> bipordbEntitiesa = new ArrayList<>();
                HashMap<String, BipordbEntity> hashMap = new HashMap<>();
                for (PrpordaVO prpordVO : prpordaVOS) {

                    PrpordaEntity prpordaEntity = prpordaDao.selectOne(new LambdaQueryWrapper<PrpordaEntity>().eq(PrpordaEntity::getId, prpordVO.getId()).eq(PrpordaEntity::getLineNum, prpordVO.getLineNum()));
                    GoodsEntity goodsEntity = goodsDao.selectOne(new LambdaQueryWrapper<GoodsEntity>().eq(GoodsEntity::getGoodsNum, prpordaEntity.getItemId()));
                    BomordEntity bomordEntity = bomordDao.selectOne(new LambdaQueryWrapper<BomordEntity>().eq(BomordEntity::getBomId, goodsEntity.getBomId()).eq(BomordEntity::getParentId, 0));

                    BipordaEntity bipordaEntity = new BipordaEntity();
                    bipordaEntity.setId(bipordEntity.getId());
                    bipordaEntity.setLineNum(++lineNum);
                    bipordaEntity.setItemId(prpordaEntity.getItemId());
                    bipordaEntity.setItemName(prpordaEntity.getItemName());
                    bipordaEntity.setQty(prpordaEntity.getQty());
                    bipordaEntity.setSpecs(prpordaEntity.getSpecs());
                    bipordaEntity.setUnit(prpordaEntity.getUnit());
                    bipordaEntity.setBaseId(prpordaEntity.getId());
                    bipordaEntity.setBaseLineNum(prpordaEntity.getLineNum());
                    bipordaEntity.setReqDate(prpordaEntity.getReqDate());
                    bipordaDao.insert(bipordaEntity);
                    tree(bomordEntity, prpordaEntity, bipordEntity.getId(), bipordaEntity.getLineNum(), goodsEntity, bipordbEntitiesa, hashMap);
                }

                int lineNuma = 1;
                for (BipordbEntity bipordbEntity : bipordbEntitiesa) {
                    BigDecimal bigDecimal = inventordDao.selectCountQty(bipordbEntity.getItemId());
                    if (bigDecimal == null){
                        bigDecimal = BigDecimal.ZERO;
                    }
                    bipordbEntity.setLineNum(lineNuma++);
                    bipordbEntity.setInvQty(bigDecimal);
                    bipordbEntity.setQty(bipordbEntity.getReqQty().subtract(bigDecimal) );
                    if (bipordbEntity.getQty().compareTo(BigDecimal.ZERO) <= 0) {
                        continue;
                    }
                    bipordbDao.insert(bipordbEntity);
                }
                for (Map.Entry<String, BipordbEntity> entry : hashMap.entrySet()) {
                    String itemId = entry.getKey();
                    BipordbEntity bipordbEntity = entry.getValue();
                    BigDecimal bigDecimal = inventordDao.selectCountQty(itemId);
                    if (bigDecimal == null){
                        bigDecimal = BigDecimal.ZERO;
                    }
                    bipordbEntity.setLineNum(lineNuma++);
                    bipordbEntity.setInvQty(bigDecimal);
                    bipordbEntity.setQty(bipordbEntity.getReqQty().subtract(bigDecimal));
                    if (bipordbEntity.getQty().compareTo(BigDecimal.ZERO) <= 0) {
                        continue;
                    }
                    bipordbDao.insert(bipordbEntity);
                }


                

            } finally {
                reentrantLock.unlock();
            }
            return ResponseDTO.ok(bipordEntity.getId());
        } else {
            return ResponseDTO.error(ErpErrorCode.PARAM_ERROR, redisService.get("key"));
        }


    }


    public Boolean upDateVesrion(Long id, Integer version) {

        PrpordEntity entity = prpordDao.selectOne(new LambdaQueryWrapper<PrpordEntity>().eq(PrpordEntity::getId, id).eq(PrpordEntity::getVersion, version));

        if (entity == null) return false;

        return prpordDao.updateById(entity) != 0;
    }


    private void tree(BomordEntity bomordEntity, PrpordaEntity prpordaEntity, Long id, Integer baseLineNum, GoodsEntity goodsEntity1, ArrayList<BipordbEntity> lista, Map<String, BipordbEntity> hashMap) {

        BipordbEntity bipordbEntity = new BipordbEntity();
        bipordbEntity.setId(id);
        bipordbEntity.setBaseId(id);
        bipordbEntity.setBaseLineNum(baseLineNum);
        bipordbEntity.setItemId(bomordEntity.getBomId());
        bipordbEntity.setItemName(bomordEntity.getBomName());
        bipordbEntity.setUnit(bomordEntity.getUnit());
        bipordbEntity.setSpecs(goodsEntity1.getSpecs());
        bipordbEntity.setSource(goodsEntity1.getSource());


        // 需求数量
        bipordbEntity.setReqQty(bomordEntity.getQty().multiply(prpordaEntity.getQty()));


        BigDecimal bigDecimal = inventordDao.selectCountQty(bomordEntity.getBomId());


        if (bigDecimal == null){
            bigDecimal = BigDecimal.ZERO;
        }


        // 库存数量
        bipordbEntity.setInvQty(bigDecimal);

        // 下达数量


        bipordbEntity.setConnum(prpordaEntity.getConnum());


        // 生产
        if ("01".equals(goodsEntity1.getSource())) {


            lista.add(bipordbEntity);


            // 采购
        } else {

            if (hashMap.containsKey(bipordbEntity.getItemId())){
                BipordbEntity bipordbEntitya = hashMap.get(bipordbEntity.getItemId());
                bipordbEntitya.setReqQty(bipordbEntitya.getReqQty().add(bipordbEntity.getReqQty()));

                hashMap.put(bipordbEntity.getItemId(),bipordbEntitya);
            } else {
                hashMap.put(bipordbEntity.getItemId(),bipordbEntity);
            }

        }

        List<BomordEntity> bomordEntities = bomordDao.selectList(new LambdaQueryWrapper<BomordEntity>().eq(BomordEntity::getParentId, bomordEntity.getId()));
        for (BomordEntity entity : bomordEntities) {
            GoodsEntity goodsEntity = goodsDao.selectOne(new LambdaQueryWrapper<GoodsEntity>().eq(GoodsEntity::getGoodsNum, entity.getBomId()));

            if ("01".equals(goodsEntity.getSource())) {
                BomordEntity bomord = bomordDao.selectOne(new LambdaQueryWrapper<BomordEntity>().eq(BomordEntity::getBomId, goodsEntity.getGoodsNum()).eq(BomordEntity::getParentId, 0));
                bomord.setQty(bomord.getQty().multiply(bomordEntity.getQty()).multiply(entity.getQty()));
                tree(bomord, prpordaEntity, id, baseLineNum, goodsEntity, lista, hashMap);
            } else {
                entity.setQty(entity.getQty().multiply(bomordEntity.getQty()));
                tree(entity, prpordaEntity, id, baseLineNum, goodsEntity, lista, hashMap);
            }
        }
    }


    public ResponseDTO<List<PrpordaVO>> queryList(PrpordQueryForm query) {
        List<PrpordaEntity> prpordaEntities = prpordaDao.selectList(null);
        List<PrpordaVO> prpordaVOS = SmartBeanUtil.copyList(prpordaEntities, PrpordaVO.class);
        return ResponseDTO.ok(prpordaVOS);
    }


}
